Extend _gdk_windowing_window_at_pointer to be able to get toplevels only
authorAlexander Larsson <alexl@redhat.com>
Mon, 28 Sep 2009 13:21:54 +0000 (15:21 +0200)
committerAlexander Larsson <alexl@redhat.com>
Mon, 28 Sep 2009 13:21:54 +0000 (15:21 +0200)
This has two advantages:
1) In many backends, this is faster as we can terminate the window
hierarchy traversal earlier
2) When used in gdkdisplay.c::get_current_toplevel() to get the
current toplevel that has the pointer we now correctly return
a toplevel with the pointer in it where the pointer is inside
some foreign subwindow of a toplevel window.

The second advantage fixes some bugs in client side event generation
when the pointer is inside such a foreign child window.

gdk/directfb/gdkwindow-directfb.c
gdk/gdkdisplay.c
gdk/gdkinternals.h
gdk/quartz/gdkwindow-quartz.c
gdk/win32/gdkwindow-win32.c
gdk/x11/gdkwindow-x11.c

index 85859e707ac6ee6f8811497c6f7f32c1cd53ba67..c0ff8e158f8309599964a1b4432ffaa6343bf22d 100644 (file)
@@ -2099,6 +2099,26 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
   if (win_y)
     *win_y = wy;
 
+  if (get_toplevel)
+    {
+      GdkWindowObject *w = (GdkWindowObject *)retval;
+      /* Requested toplevel, find it. */
+      /* TODO: This can be implemented more efficient by never
+        recursing into children in the first place */
+      if (w)
+       {
+         /* Convert to toplevel */
+         while (w->parent != NULL &&
+                w->parent->window_type != GDK_WINDOW_ROOT)
+           {
+             *win_x += w->x;
+             *win_y += w->y;
+             w = w->parent;
+           }
+         retval = (GdkWindow *)w;
+       }
+    }
+
   return retval;
 }
 
index d22ff00c77fdfe534739d49e83280285f196af52..d020b16fc30be6acf7bb056db6a8fe87187a27d7 100644 (file)
@@ -510,7 +510,7 @@ gdk_display_real_get_window_at_pointer (GdkDisplay *display,
   GdkWindow *window;
   gint x, y;
 
-  window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL);
+  window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL, FALSE);
 
   /* This might need corrections, as the native window returned
      may contain client side children */
@@ -913,34 +913,20 @@ get_current_toplevel (GdkDisplay *display,
                      GdkModifierType *state_out)
 {
   GdkWindow *pointer_window;
-  GdkWindowObject *w;
   int x, y;
   GdkModifierType state;
 
-  pointer_window = _gdk_windowing_window_at_pointer (display,  &x, &y, &state);
+  pointer_window = _gdk_windowing_window_at_pointer (display,  &x, &y, &state, TRUE);
   if (pointer_window != NULL &&
       (GDK_WINDOW_DESTROYED (pointer_window) ||
        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
     pointer_window = NULL;
 
-  w = (GdkWindowObject *)pointer_window;
-  if (w)
-    {
-      /* Convert to toplevel */
-      while (w->parent != NULL &&
-            w->parent->window_type != GDK_WINDOW_ROOT)
-       {
-         x += w->x;
-         y += w->y;
-         w = w->parent;
-       }
-    }
-
   *x_out = x;
   *y_out = y;
   *state_out = state;
-  return (GdkWindow *)w;
+  return pointer_window;
 }
 
 static void
index de082bdaa772d6ce036cf3a2ee99ad18f4bc0d28..51db55f2df83591b23470063c0b13be2d7a7f170 100644 (file)
@@ -461,7 +461,8 @@ void       _gdk_windowing_get_pointer        (GdkDisplay       *display,
 GdkWindow* _gdk_windowing_window_at_pointer  (GdkDisplay       *display,
                                              gint             *win_x,
                                              gint             *win_y,
-                                             GdkModifierType  *mask);
+                                             GdkModifierType  *mask,
+                                             gboolean          get_toplevel);
 GdkGrabStatus _gdk_windowing_pointer_grab    (GdkWindow        *window,
                                              GdkWindow        *native,
                                              gboolean          owner_events,
index ac22d5f313d0533501c91e47c8c5203d0f71ebc9..476449834091d7d69254bbd6b9267d8ed97c53a1 100644 (file)
@@ -1938,7 +1938,8 @@ GdkWindow *
 _gdk_windowing_window_at_pointer (GdkDisplay      *display,
                                  gint            *win_x,
                                  gint            *win_y,
-                                  GdkModifierType *mask)
+                                  GdkModifierType *mask,
+                                 gboolean         get_toplevel)
 {
   GdkWindow *found_window;
   gint x, y;
@@ -1976,6 +1977,26 @@ _gdk_windowing_window_at_pointer (GdkDisplay      *display,
   if (mask)
     *mask = tmp_mask;
 
+  if (get_toplevel)
+    {
+      GdkWindowObject *w = (GdkWindowObject *)found_window;
+      /* Requested toplevel, find it. */
+      /* TODO: This can be implemented more efficient by never
+        recursing into children in the first place */
+      if (w)
+       {
+         /* Convert to toplevel */
+         while (w->parent != NULL &&
+                w->parent->window_type != GDK_WINDOW_ROOT)
+           {
+             *win_x += w->x;
+             *win_y += w->y;
+             w = w->parent;
+           }
+         found_window = (GdkWindow *)w;
+       }
+    }
+
   return found_window;
 }
 
index c94563165cd97bd5cbb5fd6c1659182f99515623..e472b914c557ab96391ced3663a27e626107b504 100644 (file)
@@ -2261,7 +2261,8 @@ GdkWindow*
 _gdk_windowing_window_at_pointer (GdkDisplay *display,
                                  gint       *win_x,
                                  gint       *win_y,
-                                 GdkModifierType *mask)
+                                 GdkModifierType *mask,
+                                 gboolean    get_toplevel)
 {
   GdkWindow *window;
   POINT point, pointc;
@@ -2283,6 +2284,11 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
   ScreenToClient (hwnd, &point);
 
   do {
+    if (get_toplevel &&
+       (window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd)) != NULL &&
+       GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+      break;
+
     hwndc = ChildWindowFromPoint (hwnd, point);
     ClientToScreen (hwnd, &point);
     ScreenToClient (hwndc, &point);
index 257dba7ef66e1c41629e46fa0f188af95d01235b..f98290b6a2861368dd75938b14188779fabfb0ce 100644 (file)
@@ -3215,7 +3215,8 @@ GdkWindow*
 _gdk_windowing_window_at_pointer (GdkDisplay *display,
                                   gint       *win_x,
                                  gint       *win_y,
-                                 GdkModifierType *mask)
+                                 GdkModifierType *mask,
+                                 gboolean   get_toplevel)
 {
   GdkWindow *window;
   GdkScreen *screen;
@@ -3251,6 +3252,10 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
       while (xwindow)
        {
          xwindow_last = xwindow;
+         if (get_toplevel &&
+             (window = gdk_window_lookup_for_display (display, xwindow)) != NULL &&
+             GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+           break;
          XQueryPointer (xdisplay, xwindow,
                         &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
        }
@@ -3310,6 +3315,10 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
       while (xwindow)
        {
          xwindow_last = xwindow;
+         if (get_toplevel &&
+             (window = gdk_window_lookup_for_display (display, xwindow)) != NULL &&
+             GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+           break;
          gdk_error_trap_push ();
          XQueryPointer (xdisplay, xwindow,
                         &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);